/*
 * Copyright (c) 2025 lhjhit
 *
 * SPDX-License-Identifier: Apache-2.0
 */
// #include <inttypes.h>

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
// #include <zephyr/sys/printk.h>
// #include <zephyr/sys/util.h>
// #include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>

#include "servo_motor.h"
#include "ble.h"
#include "led.h"
#include "adc.h"

LOG_MODULE_REGISTER(MAIN_MODULE, LOG_LEVEL_INF);

#define SW0_NODE	DT_ALIAS(sw0)
#if !DT_NODE_HAS_STATUS_OKAY(SW0_NODE)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif

#define STACK_SIZE 1024
#define PRIORITY_ROTATION 2
#define PRIORITY_ADC 4
#define PRIORITY_BLE 3

k_tid_t id_thread_rotation;
K_THREAD_STACK_DEFINE(stack_area_rotation, STACK_SIZE);
static struct k_thread thread_data_rotation;

k_tid_t id_thread_adc;
K_THREAD_STACK_DEFINE(stack_area_adc, STACK_SIZE);
static struct k_thread thread_data_adc;

k_tid_t id_thread_ble;
K_THREAD_STACK_DEFINE(stack_area_ble, STACK_SIZE);
static struct k_thread thread_data_ble;

static const struct gpio_dt_spec	button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
static struct gpio_callback 	button_cb_data;

static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
	LOG_INF("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
	is_working = !is_working;
}

static int button_initialization(void)
{
	int ret;

	if (!gpio_is_ready_dt(&button)) {
		LOG_ERR("Error: button device %s is not ready\n", button.port->name);
		return -EIO;
	}

	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret != 0) {
		LOG_ERR("Error %d: failed to configure %s pin %d\n", ret, button.port->name, button.pin);
		return -EIO;
	}

	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
	if (ret != 0) {
		LOG_ERR("Error %d: failed to configure interrupt on %s pin %d\n", ret, button.port->name, button.pin);
		return -EIO;
	}

	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);

	return 0;
}

int main(void)
{
	if (led_setup()) return 0;
	blink_start();

	//TODO: use K_THREAD_DEFINE
	id_thread_rotation = k_thread_create(&thread_data_rotation, 
											stack_area_rotation, K_THREAD_STACK_SIZEOF(stack_area_rotation), 
											thread_movement, 
											NULL, NULL, NULL, 
											PRIORITY_ROTATION, 0, K_FOREVER);

	id_thread_adc = k_thread_create(&thread_data_adc, 
										stack_area_adc, K_THREAD_STACK_SIZEOF(stack_area_adc), 
										thread_adc, 
										NULL, NULL, NULL, 
										PRIORITY_ADC, 0, K_FOREVER);

	id_thread_ble = k_thread_create(&thread_data_ble, 
										stack_area_ble, K_THREAD_STACK_SIZEOF(stack_area_ble), 
										thread_ble, 
										NULL, NULL, NULL, 
										PRIORITY_BLE, 0, K_FOREVER);

	k_thread_name_set(&thread_data_rotation, "thread_rotation");
	k_thread_name_set(&thread_data_adc, "thread_adc");
	k_thread_name_set(&thread_data_ble, "thread_ble");

	if (button_initialization()) {
		LOG_ERR("Error: button_initialization failed!\n");
	}

	k_thread_start(&thread_data_rotation);
	k_thread_start(&thread_data_adc);
	k_thread_start(&thread_data_ble);
}